# [六] Bean的实例化-注解支持
注解支持
注解的实现过程,其实就是Spring Bean的自动装配过程,存在于Srping bean的生命周期中,Spirng 中有三种bean的装配机制:
- 1、xml进行显示配置
- 2、java中进行显示配置
- 3、隐式的bean发现机制和自动装配 所以要想了解Spring中的注解原理,首先需要了解注解的装配过程。
# 注解处理的入口
Spring初始化过程中,调用注解处理的几个主要埋点
│ ├─
refresh│ │ ├─
prepareRefresh│ │ ├─
obtainFreshBeanFactory XML文件解析,component-scan属性解析│ │ ├─
prepareBeanFactory│ │ ├─
postProcessBeanFactory│ │ ├─
invokeBeanFactoryPostProcessors│ │ ├─
registerBeanPostProcessors 实例化注解处理器│ │ ├─
initMessageSource│ │ ├─
initApplicationEventMulticaster│ │ ├─
registerListeners│ │ ├─
finishBeanFactoryInitialization│ │ ├─
getObjectForBeanInstance│ │ ├─
getBean│ │ │ ├─
createBean│ │ │ │ ├─
doCreateBean│ │ │ │ │ ├─
createBeanInstance│ │ │ │ │ │ ├─
determineConstructorsFromBeanPostProcessors 解析构造函数是否有@Autowired│ │ │ │ │ ├─
applyMergedBeanDefinitionPostProcessors 注解的搜集和装配过程│ │ │ │ │ ├─
earlySingletonExposure│ │ │ │ │ ├─
addSingletonFactory│ │ │ │ │ ├─
populateBean│ │ │ │ │ │ ├─
postProcessProperties 根据收集到的注解进行反射调用│ │ │ │ │ │ │ ├─
AutowiredFieldElement.inject 解析有@Autowired注解域的注入│ │ │ │ │ │ │ ├─
AutowiredMethodElement.inject 解析有@Autowired注解方法的注入│ │ │ │ │ ├─
initializeBean│ │ │ │ │ │ ├─
applyBeanPostProcessorsBeforeInitialization 解析处理@PostConstruct│ │ │ │ │ │ ├─
invokeInitMethods│ │ │ │ │ │ ├─
applyBeanPostProcessorsAfterInitialization AOP的入口│ │ │ ├─
afterSingletonCreation│ │ │ └─
addSingleton
# 注解的装配与收集
装配过程
1、根据xml文件
<context:component-scan>
标签中的类路径或者@ComponentScan注解中的类路径进行扫描解析,将包含@Component和元注解为@Component的注解@Controller、@Service、@Repository还有支持Java EE 6的@link javax.annotation.ManagedBean
和JSR-330的 @link javax.inject.Named
的bean封装到BeanDefinition对象后,最后注册到BeanFactory
中。2、注册注解后置处理器,主要由
BeanPostProcessor
来负责解析,具体包括:- ConfigurationClassPostProcessor: 注册@Configuration处理器。
AutowiredAnnotationBeanPostProcessor
:注册@Autowired、@Value、@Inject(JSR-330)处理器。RequiredAnnotationBeanPostProcessor
:注册@Required处理器。PersistenceAnnotationBeanPostProcessor
:支持Jpa的条件下,处理Jpa相关注解 。EventListenerMethodProcessor
:注册@EventListener处理器。InitDestroyAnnotationBeanPostProcessor
:处理@PostConstruct、@PreDestroy 注解的解析。CommonAnnotationBeanPostProcessor
:在支持JSR-250条件下注册JDK中javax.annotation包中注解处理器(@PostConstruct、@PreDestroy、@Resource、@Resources、@Generated)。
注解后置处理器的收集过程
@Autowired
和@Resource
注解的收集过程基本一致,流程如下:
- 1、看缓存里面有没有 InjectionMetadata对象
- 2、从类中获取所有 Field 对象,循环 Field 对象,判断 Field 有没有@Resource注解, 如果有注解封装成 ResourceElement对象
- 3、从类中获取所有 Method对象,循环 Method对象,判断 Method有没有@Resource 注解,如果有注解封装成 ResourceElement对象
- 4、然后把两个 Field 和 Method封装的对象集合封装到 InjectionMetadata对象中
- 5、最终把返回的 InjectionMetadata 对象存到ConcurrentHashMap 缓存中。
# 常用注解的处理器
# CommonAnnotationBeanPostProcessor
概述
CommonAnnotationBeanPostProcessor
支持了@PostConstruct、@PreDestroy、@Resource等注解的解析工作,但是真正对@PostConstruct、@PreDestroy两个注解的解析是由其父类InitDestroyAnnotationBeanPostProcessor
来完成的。
源码
// CommonAnnotationBeanPostProcessor的构造函数,支持了@PostConstruct、@PreDestroy
public CommonAnnotationBeanPostProcessor() {
setOrder(Ordered.LOWEST_PRECEDENCE - 3);
setInitAnnotationType(PostConstruct.class);
setDestroyAnnotationType(PreDestroy.class);
ignoreResourceType("javax.xml.ws.WebServiceContext");
}
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
//扫描@PostConstruct @PreDestroy
super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
//扫描@Resource,扫描属性和方法上面是否有@Resource注解,如果有则收集起来封装成对象
InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
# AutowiredAnnotationBeanPostProcessor
概述
AutowiredAnnotationBeanPostProcessor后置处理器,主要处理@Autowired的解析。
类图
- PriorityOrdered:确认 AutowiredAnnotationBeanPostProcessor 后置处理器的执行优先级
- BeanFactoryAware:使得AutowiredAnnotationBeanPostProcessor 可以直接通过BeanFactory获取容器中的Bean
- BeanPostProcessor:在 Bean 初始化前后执行的后置处理器
- InstantiationAwareBeanPostProcessor:在 Bean 实例化前后和Bean设置属性值时执行的后置处理器
- SmartInstantiationAwareBeanPostProcessor:智能实例化Bean的后处理器,如预测Bean的类型和确认Bean的构造函数等。
- MergedBeanDefinitionPostProcessor:合并Bean的定义信息。
Spring 注解的装配收集源码
/**
* TODO : 注解装配过程的核心方法,
* BeanPostProcessor接口的典型运用,这里要理解这个接口
*/
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof MergedBeanDefinitionPostProcessor) {
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
}
}